<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 
<html>
<head>
<title>The Puzzle in Java Swing</title>
<link rel="stylesheet" href="/cfg/format.css" type="text/css">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="keywords" content="Java, Swing, puzzle, tutorial, programming, Linux">
<meta name="description" content="This part of the Java Swing tutorial presents a Puzzle
game in Java Swing.">
<meta name="language" content="en">
<meta name="author" content="Jan Bodnar">
<meta name="distribution" content="global">

<script type="text/javascript" src="/lib/jquery.js"></script>
<script type="text/javascript" src="/lib/common.js"></script>

</head>

<body>

<div class="container">

<div id="wide_ad" class="ltow">
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* 160x600, August 2011 */
google_ad_slot = "2484182563";
google_ad_width = 160;
google_ad_height = 600;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>

<div class="content">


<a href="/" title="Home">Home</a>&nbsp;
<a href=".." title="Home">Contents</a>


<h1>The Puzzle in Java Swing</h1>


<p>
In this chapter, we will create a simple puzzle game in Java Swing toolkit. 
</p>

<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* NewSquare */
google_ad_slot = "0364418177";
google_ad_width = 300;
google_ad_height = 250;
//-->
</script> 
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> 
</script>


<h2>Puzzle</h2>

<p>
We have an image of a Sid character from the Ice Age movie. It is cut 
into 12 pieces. The goal is to form the picture. 
</p>


<pre class="code">
package zetcode;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.CropImageFilter;
import java.awt.image.FilteredImageSource;

import javax.swing.Box;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class Puzzle extends JFrame implements ActionListener {

    private JPanel centerPanel;
    private JButton button;
    private JLabel label;
    private Image source;
    private Image image;
    int[][] pos;
    int width, height;

    public Puzzle() {

        initUI();
    }

    public final void initUI() {

        pos = new int[][]{
                    {0, 1, 2},
                    {3, 4, 5},
                    {6, 7, 8},
                    {9, 10, 11}
                };


        centerPanel = new JPanel();
        centerPanel.setLayout(new GridLayout(4, 4, 0, 0));

        ImageIcon sid = new ImageIcon(Puzzle.class.getResource("icesid.jpg"));
        source = sid.getImage();

        width = sid.getIconWidth();
        height = sid.getIconHeight();


        add(Box.createRigidArea(new Dimension(0, 5)), BorderLayout.NORTH);
        add(centerPanel, BorderLayout.CENTER);


        for (int i = 0; i &lt; 4; i++) {
            for (int j = 0; j &lt; 3; j++) {
                if (j == 2 &amp;&amp; i == 3) {
                    label = new JLabel("");
                    centerPanel.add(label);
                } else {
                    button = new JButton();
                    button.addActionListener(this);
                    centerPanel.add(button);
                    image = createImage(new FilteredImageSource(source.getSource(),
                            new CropImageFilter(j * width / 3, i * height / 4,
                            (width / 3) + 1, height / 4)));
                    button.setIcon(new ImageIcon(image));
                }
            }
        }

        setSize(325, 275);
        setTitle("Puzzle");
        setResizable(false);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    }

    public void actionPerformed(ActionEvent e) {

        JButton button = (JButton) e.getSource();
        Dimension size = button.getSize();

        int labelX = label.getX();
        int labelY = label.getY();
        int buttonX = button.getX();
        int buttonY = button.getY();
        int buttonPosX = buttonX / size.width;
        int buttonPosY = buttonY / size.height;
        int buttonIndex = pos[buttonPosY][buttonPosX];



        if (labelX == buttonX &amp;&amp; (labelY - buttonY) == size.height) {

            int labelIndex = buttonIndex + 3;

            centerPanel.remove(buttonIndex);
            centerPanel.add(label, buttonIndex);
            centerPanel.add(button, labelIndex);
            centerPanel.validate();
        }

        if (labelX == buttonX &amp;&amp; (labelY - buttonY) == -size.height) {

            int labelIndex = buttonIndex - 3;
            centerPanel.remove(labelIndex);
            centerPanel.add(button, labelIndex);
            centerPanel.add(label, buttonIndex);
            centerPanel.validate();
        }

        if (labelY == buttonY &amp;&amp; (labelX - buttonX) == size.width) {

            int labelIndex = buttonIndex + 1;

            centerPanel.remove(buttonIndex);
            centerPanel.add(label, buttonIndex);
            centerPanel.add(button, labelIndex);
            centerPanel.validate();
        }

        if (labelY == buttonY &amp;&amp; (labelX - buttonX) == -size.width) {

            int labelIndex = buttonIndex - 1;

            centerPanel.remove(buttonIndex);
            centerPanel.add(label, labelIndex);
            centerPanel.add(button, labelIndex);
            centerPanel.validate();
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                Puzzle puzzle = new Puzzle();
                puzzle.setVisible(true);
            }
        });
    }
}

</pre>

<p>
The goal of this little game is to form the original picture. We move the 
buttons by clicking on them. Only buttons adjacent to the label can be moved. 
</p>

<pre class="explanation">
 pos = new int[][] {
       {0, 1, 2}, 
       {3, 4, 5}, 
       {6, 7, 8}, 
       {9, 10, 11}
 };
</pre>

<p>
These are the positions of the image parts.
</p>

<pre class="explanation">
ImageIcon sid = new ImageIcon(Puzzle.class.getResource("icesid.jpg"));
source = sid.getImage();
</pre>

<p>
We use the <code>ImageIcon</code> class to load the image. 
</p>

<pre class="explanation">
for (int i = 0; i &lt; 4; i++) {
    for (int j = 0; j &lt; 3; j++) {
        if (j == 2 &amp;&amp; i == 3) {
            label = new JLabel("");
            centerPanel.add(label);
        } else {
            button = new JButton();
            button.addActionListener(this);
            centerPanel.add(button);
            image = createImage(new FilteredImageSource(source.getSource(),
                    new CropImageFilter(j * width / 3, i * height / 4,
                    (width / 3) + 1, height / 4)));
            button.setIcon(new ImageIcon(image));
        }
    }
}
</pre>

<p>
The code creates 11 buttons and one label. We crop the image into pieces 
and place them on the buttons. 
</p>

<pre class="explanation">
int labelX = label.getX();
int labelY = label.getY();
int buttonX = button.getX();
int buttonY = button.getY();
</pre>

<p>
We get the x, y coordinates of the button that we hit and an empty label. 
The x, y coordinates are important in the logic of the program.  
</p>

<pre class="explanation">
int buttonPosX = buttonX / size.width;
int buttonPosY = buttonY / size.height;
int buttonIndex = pos[buttonPosY][buttonPosX];
</pre>

<p>
Here we get the index of the button in the two dimensional array of the button positions. 
</p>

<pre class="explanation">
if (labelX == buttonX &amp;&amp; (labelY - buttonY) == size.height ) {

    int labelIndex = buttonIndex + 3;

    centerPanel.remove(buttonIndex);
    centerPanel.add(label, buttonIndex);
    centerPanel.add(button,labelIndex);
    centerPanel.validate();
}
</pre>

<p>
In this case, we check if we clicked on the button, that is right above the 
empty label. If it is above the label, they share the x coordinate. If 
the button is right above the label, the equation 
<code>(labelY - buttonY) == size.height</code> is true. 
</p>


<img src="/img/gui/javaswing/puzzle.png" alt="Puzzle">
<div class="figure">Figure: Puzzle</div>


<p>
This was a puzzle game.
</p>


<div class="center"> 
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* horizontal */
google_ad_slot = "1734478269";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script> 
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> 
</script> 
</div>
<br>


<div class="botNav, center">
<span class="botNavItem"><a href="/">Home</a></span> ‡ <span class="botNavItem"><a href="..">Contents</a></span> ‡ 
<span class="botNavItem"><a href="#">Top of Page</a></span>
</div>


<div class="footer">
<div class="signature">
<a href="/">ZetCode</a> last modified July 14, 2008  <span class="copyright">&copy; 2007 - 2013 Jan Bodnar</span>
</div>
</div>

</div> <!-- content -->

</div> <!-- container -->

</body>
</html>

